from flask import Flask, request, jsonify, render_template_string,render_template
from flask_cors import CORS
from werkzeug.security import generate_password_hash, check_password_hash
import jwt
import datetime
import random
import sqlite3
import os
from functools import wraps

# 初始化Flask应用
app = Flask(__name__)
app.secret_key = 'nj_travel_secret_key_2025'
CORS(app)

# 数据库配置
DATABASE = 'jiangsu2.db'


def get_db_connection():
    conn = sqlite3.connect(DATABASE)
    conn.row_factory = sqlite3.Row
    return conn


def init_database():

    if os.path.exists(DATABASE):
        return

    conn = get_db_connection()
    cursor = conn.cursor()

    # 创建用户表
    cursor.execute('''
    CREATE TABLE users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        username TEXT UNIQUE NOT NULL,
        password TEXT NOT NULL,
        name TEXT NOT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )
    ''')

    # 创建景点表
    cursor.execute('''
    CREATE TABLE scenic_spots (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        full_name TEXT NOT NULL,
        short_name TEXT,
        city TEXT,
        district TEXT,
        level TEXT,
        description TEXT,
        image_url TEXT,
        likes INTEGER DEFAULT 0,
        comments INTEGER DEFAULT 0,
        bookmarks INTEGER DEFAULT 0,
        tags TEXT,
        rating REAL,
        price TEXT,
        open_time TEXT,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )
    ''')

    # 创建游记表
    cursor.execute('''
    CREATE TABLE travel_notes (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        scenic_spot_id INTEGER NOT NULL,
        note_url TEXT,
        image_urls TEXT,
        local_image_paths TEXT,
        title TEXT,
        description TEXT,
        like_count INTEGER DEFAULT 0,
        collect_count INTEGER DEFAULT 0,
        comment_count INTEGER DEFAULT 0,
        share_count INTEGER DEFAULT 0,
        crawl_time TEXT,
        FOREIGN KEY (scenic_spot_id) REFERENCES scenic_spots (id)
    )
    ''')

    # 创建用户行为表
    cursor.execute('''
    CREATE TABLE user_behavior (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        user_id INTEGER NOT NULL,
        attraction_id INTEGER NOT NULL,
        viewed BOOLEAN DEFAULT FALSE,
        liked BOOLEAN DEFAULT FALSE,
        commented BOOLEAN DEFAULT FALSE,
        timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        FOREIGN KEY (user_id) REFERENCES users (id),
        FOREIGN KEY (attraction_id) REFERENCES scenic_spots (id),
        UNIQUE(user_id, attraction_id)
    )
    ''')

    # 插入测试用户数据
    users = [
        ('admin', generate_password_hash('admin123'), '管理员'),
        ('user1', generate_password_hash('password1'), '张游客'),
        ('user2', generate_password_hash('password2'), '李旅行')
    ]
    cursor.executemany('INSERT INTO users (username, password, name) VALUES (?, ?, ?)', users)

    # 从Excel2中提取景点数据并插入
    scenic_spots = [
        ('江苏省南京市大塘金香草谷', '大塘金香草谷', '南京', '江宁区', '3A',
         '这里每年4月-10月薰衣草、马鞭草等大片盛开，紫色花海超浪漫。园区内有20多个亲子无动力项目免费开放，还有萌宠乐园可近距离接触小动物。景区内一处一景拍照嘎嘎出片！！大型节日晚上有时会有烟花秀、灯光秀等主题展演活动。',
         'http://sns-webpic-qc.xhscdn.com/202508281530/5039653ed1202ff85717658690420f3d/notes_pre_post/1040g3k031lm9oe16l0005ougu5rpi5lhib87eb8!nd_dft_wlteh_webp_3',
         12560, 3421, 5678, '自然,花海,亲子', 4.8, '50元', '09:30-17:00')
    ]
    cursor.executemany('''
    INSERT INTO scenic_spots (full_name, short_name, city, district, level, description, image_url, likes, comments, bookmarks, tags, rating, price, open_time)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    ''', scenic_spots)

    # 从Excel2中提取游记数据并插入
    travel_notes = [
        (1,
         'https://www.xiaohongshu.com/explore/68aeb6d7000000001d00f314?xsec_token=ABhj-MwMoHkp3wtfxR_wtCLE-M8oUNsvnzfxOYuTdS914=',
         'http://sns-webpic-qc.xhscdn.com/202508281530/5039653ed1202ff85717658690420f3d/notes_pre_post/1040g3k031lm9oe16l0005ougu5rpi5lhib87eb8!nd_dft_wlteh_webp_3,http://sns-webpic-qc.xhscdn.com/202508281530/691e813df8c2c497348b8b812bcbdb67/notes_pre_post/1040g3k831lm9ofcc50005ougu5rpi5lhclkpdr8!nd_dft_wgth_webp_3',
         'D:/app/PyCharm/Py_Projects/Spider_XHS-master/datas/media_datas/jiangsu_scenic_spots/大塘金香草谷_63d0f17700000000260116b1/南京江宁谷里旅游攻略来啦！_68aeb6d7000000001d00f314/image_0.jpg,D:/app/PyCharm/Py_Projects/Spider_XHS-master/datas/media_datas/jiangsu_scenic_spots/大塘金香草谷_63d0f17700000000260116b1/南京江宁谷里旅游攻略来啦！_68aeb6d7000000001d00f314/image_1.jpg',
         '南京江宁谷里旅游攻略来啦！',
         '带你玩转大塘金香草谷，牛首山、银杏湖乐园和松鼠咔咔森林乐园，赶紧收藏吧！\n大塘金香草谷\n门票：50元，可能有不同票价（具体看活动）\n开放时间：09：30 - 17：00\n这里每年4月 - 10月薰衣草、马鞭草等大片盛开，紫色花海超浪漫。园区内有20多个亲子无动力项目免费开放，还有萌宠乐园可近距离接触小动物 。景区内一处一景 拍照嘎嘎出片！！大型节日晚上有时会有烟花秀、灯光秀等主题展演活动（需关注景区预告）。',
         0, 0, 0, 0, '2025-08-28 07:30:35')
    ]
    cursor.executemany('''
    INSERT INTO travel_notes (scenic_spot_id, note_url, image_urls, local_image_paths, title, description, like_count, collect_count, comment_count, share_count, crawl_time)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    ''', travel_notes)

    # 插入用户行为数据
    behaviors = [
        (2, 1, True, True, False),  # user1 浏览并点赞大塘金香草谷
        (3, 1, True, False, True),  # user2 浏览并评论大塘金香草谷
        (1, 1, True, True, True)  # admin 浏览、点赞并评论大塘金香草谷
    ]
    cursor.executemany('''
    INSERT INTO user_behavior (user_id, attraction_id, viewed, liked, commented)
    VALUES (?, ?, ?, ?, ?)
    ''', behaviors)

    conn.commit()
    conn.close()


# JWT令牌验证装饰器
def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = request.headers.get('Authorization')
        if not token:
            return jsonify({'success': False, 'message': 'Token is missing'}), 401

        try:
            if token.startswith('Bearer '):
                token = token[7:]
            data = jwt.decode(token, app.secret_key, algorithms=['HS256'])
            current_user = data['user']
        except jwt.ExpiredSignatureError:
            return jsonify({'success': False, 'message': 'Token has expired'}), 401
        except jwt.InvalidTokenError:
            return jsonify({'success': False, 'message': 'Token is invalid'}), 401
        except Exception:
            return jsonify({'success': False, 'message': 'Token verification failed'}), 401

        return f(current_user, *args, **kwargs)

    return decorated


# 根路由
@app.route('/')
def index():
    return render_template_string(FRONTEND_HTML)


# 登录接口
@app.route('/api/login', methods=['POST'])
def login():
    try:
        auth_data = request.get_json()
        if not auth_data or not auth_data.get('username') or not auth_data.get('password'):
            return jsonify({'success': False, 'message': '用户名和密码不能为空'}), 400

        username = auth_data['username']
        password = auth_data['password']

        conn = get_db_connection()
        user = conn.execute('SELECT * FROM users WHERE username = ?', (username,)).fetchone()
        conn.close()

        if not user:
            return jsonify({'success': False, 'message': '用户不存在'}), 401

        if check_password_hash(user['password'], password):
            token = jwt.encode({
                'user': username,
                'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=24)
            }, app.secret_key, algorithm='HS256')

            return jsonify({
                'success': True,
                'name': user['name'],
                'token': token
            })
        else:
            return jsonify({'success': False, 'message': '密码错误'}), 401

    except Exception as e:
        return jsonify({'success': False, 'message': f'登录失败: {str(e)}'}), 500


# 推荐景点接口
@app.route('/api/recommend', methods=['GET'])
@token_required
def recommend(current_user):
    try:
        conn = get_db_connection()

        # 获取用户ID
        user = conn.execute('SELECT id FROM users WHERE username = ?', (current_user,)).fetchone()
        if not user:
            conn.close()
            return jsonify({'success': False, 'message': '用户不存在'}), 404

        user_id = user['id']

        # 获取用户浏览过的景点ID列表
        viewed_attractions = [b['attraction_id'] for b in
                              conn.execute('SELECT attraction_id FROM user_behavior WHERE user_id = ? AND viewed = 1',
                                           (user_id,)).fetchall()]

        # 如果没有历史记录，返回热门推荐
        if not viewed_attractions:
            attractions = conn.execute('''
                SELECT * FROM scenic_spots 
                ORDER BY likes DESC 
                LIMIT 4
            ''').fetchall()
        else:
            # 获取用户点赞过的景点标签
            liked_tags = conn.execute('''
                SELECT GROUP_CONCAT(tags) as all_tags 
                FROM scenic_spots 
                WHERE id IN (
                    SELECT attraction_id FROM user_behavior 
                    WHERE user_id = ? AND liked = 1
                )
            ''', (user_id,)).fetchone()['all_tags']

            if liked_tags:
                unique_tags = list(set(liked_tags.split(',')))

                # 查询包含这些标签的景点
                query = '''
                    SELECT * FROM scenic_spots 
                    WHERE id NOT IN ({}) 
                    AND (
                '''.format(','.join(['?'] * len(viewed_attractions)))

                query += ' OR '.join(['tags LIKE ?' for _ in unique_tags])
                query += ') ORDER BY rating DESC, likes DESC LIMIT 4'

                params = viewed_attractions + [f'%{tag}%' for tag in unique_tags]
                attractions = conn.execute(query, params).fetchall()

                # 如果不够4个，补充热门景点
                if len(attractions) < 4:
                    remaining = 4 - len(attractions)
                    additional = conn.execute('''
                        SELECT * FROM scenic_spots 
                        WHERE id NOT IN ({}) 
                        ORDER BY likes DESC 
                        LIMIT ?
                    '''.format(','.join(['?'] * len(viewed_attractions))),
                                              viewed_attractions + [remaining]).fetchall()

                    attractions.extend(additional)
            else:
                # 如果没有点赞记录，基于浏览记录推荐
                attractions = conn.execute('''
                    SELECT * FROM scenic_spots 
                    WHERE id NOT IN ({}) 
                    ORDER BY rating DESC, likes DESC 
                    LIMIT 4
                '''.format(','.join(['?'] * len(viewed_attractions))), viewed_attractions).fetchall()

        conn.close()

        # 转换为字典列表
        result = [dict(att) for att in attractions]
        return jsonify({
            'success': True,
            'data': result,
            'user': current_user
        })

    except Exception as e:
        if 'conn' in locals():
            conn.close()
        return jsonify({'success': False, 'message': f'获取推荐失败: {str(e)}'}), 500


# 景点排名接口
@app.route('/api/rank', methods=['GET'])
def rank():
    try:
        conn = get_db_connection()

        # 多维度排序：点赞数(50%) + 收藏数(30%) + 评论数(20%)
        attractions = conn.execute('''
            SELECT *, 
                   (likes * 0.5 + bookmarks * 0.3 + comments * 0.2) as score 
            FROM scenic_spots 
            ORDER BY score DESC
        ''').fetchall()

        conn.close()

        # 添加排名和趋势信息
        result = []
        for i, att in enumerate(attractions):
            item = dict(att)
            item['rank'] = i + 1
            item['trend'] = random.choice(['up', 'down', 'stable'])
            result.append(item)

        return jsonify({
            'success': True,
            'data': result,
            'last_updated': datetime.datetime.now().isoformat()
        })

    except Exception as e:
        if 'conn' in locals():
            conn.close()
        return jsonify({'success': False, 'message': f'获取排名失败: {str(e)}'}), 500
# 搜索处理函数
def search_database(keyword):
    """在数据库中执行搜索"""
    conn = get_db_connection()

    search_pattern = f'%{keyword}%'

    # 在多个字段中搜索
    query = '''
    SELECT * FROM scenic_spots 
    WHERE full_name LIKE ? OR short_name LIKE ? 
          OR description LIKE ? OR tags LIKE ? 
          OR city LIKE ? OR district LIKE ?
    ORDER BY 
        CASE 
            WHEN full_name LIKE ? THEN 1
            WHEN short_name LIKE ? THEN 2
            WHEN tags LIKE ? THEN 3
            ELSE 4
        END,
        rating DESC, 
        likes DESC
    LIMIT 20
    '''

    params = [search_pattern] * 6 + [f'%{keyword}%', f'%{keyword}%', f'%{keyword}%']
    results = conn.execute(query, params).fetchall()

    conn.close()
    return [dict(result) for result in results]


# 修改现有的搜索API路由，同时支持JSON和HTML响应
@app.route('/api/search', methods=['GET'])
def search():
    try:
        keyword = request.args.get('q', '').strip()
        if not keyword:
            if request.accept_mimetypes.accept_json:
                return jsonify({'success': False, 'message': '搜索关键词不能为空'}), 400
            else:
                return render_template_string('<p>请输入搜索关键词</p>')

        # 执行搜索
        search_results = search_database(keyword)

        # 根据请求类型返回不同响应
        if request.accept_mimetypes.accept_json:
            return jsonify({
                'success': True,
                'data': search_results,
                'keyword': keyword,
                'count': len(search_results)
            })
        else:
            # 返回HTML渲染的搜索结果
            return render_template_string('''
            <div class="search-results">
                <h3>搜索 "{{ keyword }}" 的结果 ({{ results|length }} 个)</h3>
                {% for item in results %}
                <div class="result-card">
                    <h4>{{ item.full_name }}</h4>
                    <p class="description">{{ item.description[:150] }}...</p>
                    <div class="stats">
                        <span class="likes">👍 {{ item.likes }}</span>
                        <span class="comments">💬 {{ item.comments }}</span>
                        <span class="rating">⭐ {{ item.rating }}</span>
                        <span class="price">💰 {{ item.price }}</span>
                    </div>
                    <div class="location">
                        📍 {{ item.city }} - {{ item.district }}
                    </div>
                </div>
                {% else %}
                <p class="no-results">没有找到相关结果</p>
                {% endfor %}
            </div>
            ''', results=search_results, keyword=keyword)

    except Exception as e:
        if request.accept_mimetypes.accept_json:
            return jsonify({'success': False, 'message': f'搜索失败: {str(e)}'}), 500
        else:
            return render_template_string('<p class="error">搜索失败，请稍后重试</p>')


@app.route('/search')
def search_page():
    """显示搜索页面和处理搜索请求"""
    keyword = request.args.get('q', '').strip()

    # 如果有搜索关键词，执行搜索
    if keyword:
        try:
            search_results = search_database(keyword)  # 调用搜索函数
        except Exception as e:
            print(f"搜索错误: {e}")
            search_results = []
    else:
        search_results = []

    # 渲染模板并传递结果
    return render_template_string('''
    <!DOCTYPE html>
    <html>
    <head>
        <title>搜索 - 南京旅游小红书</title>
        <style>
            .search-container { max-width: 800px; margin: 40px auto; padding: 20px; }
            .search-form { display: flex; margin-bottom: 30px; }
            .search-input { 
                flex: 1; padding: 12px; border: 2px solid #6a11cb; 
                border-radius: 8px 0 0 8px; font-size: 16px; 
            }
            .search-button { 
                padding: 12px 24px; background: #6a11cb; color: white; 
                border: none; border-radius: 0 8px 8px 0; cursor: pointer; 
            }
            .results-container { margin-top: 20px; }
            .result-item { 
                background: white; padding: 20px; margin-bottom: 15px; 
                border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); 
            }
            .no-results { text-align: center; color: #666; padding: 40px; }
        </style>
    </head>
    <body>
        <div class="search-container">
            <form class="search-form" action="/search" method="GET">
                <input type="text" name="q" class="search-input" 
                       placeholder="输入景点名称、描述或标签..." 
                       value="{{ keyword }}">
                <button type="submit" class="search-button">搜索</button>
            </form>

            <div class="results-container">
                {% if keyword and search_results %}
                    <h3>找到 {{ search_results|length }} 个与 "{{ keyword }}" 相关的结果</h3>
                    {% for item in search_results %}
                    <div class="result-item">
                        <h4>{{ item.full_name }}</h4>
                        <p>{{ item.description[:200] }}{% if item.description|length > 200 %}...{% endif %}</p>
                        <div class="result-stats">
                            <span>👍 {{ item.likes or 0 }}</span>
                            <span>💬 {{ item.comments or 0 }}</span>
                            <span>⭐ {{ item.rating or 0 }}</span>
                        </div>
                    </div>
                    {% endfor %}
                {% elif keyword %}
                    <div class="no-results">
                        <p>没有找到与 "{{ keyword }}" 相关的结果</p>
                    </div>
                {% endif %}
            </div>
        </div>
    </body>
    </html>
    ''', search_results=search_results, keyword=keyword)

# 前端HTML模板
FRONTEND_HTML = """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>南京旅游小红书 - 发现金陵之美</title>
    <link rel="stylesheet" href="链接1">
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif; }
        body { background-color: #f7f9fc; color: #333; line-height: 1.6; }
        .container { max-width: 1200px; margin: 0 auto; padding: 0 20px; }

        /* 导航栏样式 */
        header { background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%); color: white; padding: 15px 0; box-shadow: 0 4px 12px rgba(0,0,0,0.1); position: sticky; top: 0; z-index: 100; }
        .navbar { display: flex; justify-content: space-between; align-items: center; }
        .logo { font-size: 24px; font-weight: bold; display: flex; align-items: center; }
        .logo i { margin-right: 8px; color: #ff2e63; }
        .nav-links { display: flex; list-style: none; }
        .nav-links li { margin-left: 30px; }
        .nav-links a { color: white; text-decoration: none; font-weight: 500; transition: all 0.3s ease; }
        .nav-links a:hover { color: #ffd166; }
        .search-box { display: flex; align-items: center; background: rgba(255,255,255,0.2); border-radius: 20px; padding: 5px 15px; }
        .search-box input { background: transparent; border: none; color: white; padding: 8px; width: 200px; outline: none; }
        .search-box input::placeholder { color: rgba(255,255,255,0.7); }
        .login-btn { background: #ffd166; color: #2d334a; border: none; border-radius: 18px; padding: 8px 22px; font-weight: 600; margin-left: 18px; cursor: pointer; transition: background 0.3s; }
        .login-btn:hover { background: #fff3e0; color: #6a11cb; }
        .user-info { color: #fff; font-weight: 600; background: #ff2e63; border-radius: 18px; padding: 8px 22px; margin-left: 18px; display: flex; align-items: center; }
        .logout-btn { background: transparent; border: none; color: #fff; margin-left: 12px; cursor: pointer; font-size: 1rem; text-decoration: underline; }

        /* 猜你喜欢区域 */
        .recommendation-section { padding: 40px 0; text-align: center; }
        .section-title { font-size: 28px; margin-bottom: 30px; color: #2d334a; position: relative; display: inline-block; }
        .section-title::after { content: ''; position: absolute; bottom: -10px; left: 50%; transform: translateX(-50%); width: 50px; height: 3px; background: linear-gradient(90deg, #6a11cb, #2575fc); }
        .section-subtitle { color: #666; margin-bottom: 20px; }
        .recommendation-cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 25px; margin-top: 20px; }
        .card { background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 5px 15px rgba(0,0,0,0.08); transition: transform 0.3s, box-shadow 0.3s; cursor: pointer; }
        .card:hover { transform: translateY(-5px); box-shadow: 0 10px 25px rgba(0,0,0,0.15); }
        .card-img { height: 180px; overflow: hidden; }
        .card-img img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s; }
        .card:hover .card-img img { transform: scale(1.05); }
        .card-content { padding: 20px; }
        .card-title { font-size: 18px; font-weight: 600; margin-bottom: 10px; color: #2d334a; }
        .card-desc { font-size: 14px; color: #666; margin-bottom: 15px; }
        .card-stats { display: flex; justify-content: space-between; color: #888; font-size: 13px; }

        /* 实时排名区域 */
        .ranking-section { padding: 40px 0; background: white; border-radius: 15px; box-shadow: 0 5px 20px rgba(0,0,0,0.05); margin-bottom: 40px; }
        .ranking-list { counter-reset: ranking; }
        .ranking-item { display: flex; align-items: center; padding: 20px; border-bottom: 1px solid #eee; transition: background 0.3s; cursor: pointer; }
        .ranking-item:hover { background: #f9f9f9; }
        .ranking-number { width: 30px; height: 30px; background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%); color: white; border-radius: 50%; display: flex; justify-content: center; align-items: center; font-weight: bold; margin-right: 20px; flex-shrink: 0; }
        .ranking-item:nth-child(-n+3) .ranking-number { background: linear-gradient(135deg, #ff0844 0%, #ffb199 100%); }
        .ranking-content { flex-grow: 1; }
        .ranking-title { font-size: 18px; font-weight: 600; margin-bottom: 5px; color: #2d334a; }
        .ranking-desc { font-size: 14px; color: #666; margin-bottom: 10px; }
        .ranking-stats { display: flex; color: #888; font-size: 13px; }
        .ranking-stats span { margin-right: 15px; display: flex; align-items: center; }
        .ranking-stats i { margin-right: 5px; }
        .ranking-img { width: 100px; height: 70px; border-radius: 8px; overflow: hidden; margin-left: 20px; flex-shrink: 0; }
        .ranking-img img { width: 100%; height: 100%; object-fit: cover; }
        .refresh-btn { background: #ffd166; color: #2d334a; border: none; border-radius: 18px; padding: 8px 22px; font-weight: 600; margin-left: 18px; cursor: pointer; transition: background 0.3s; }
        .refresh-btn:hover { background: #fff3e0; color: #6a11cb; }

        /* 登录弹窗样式 */
        .login-modal { display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100vw; height: 100vh; background: rgba(30,30,30,0.17); justify-content: center; align-items: center; }
        .login-modal.active { display: flex; }
        .login-box { background: #fff; min-width: 270px; max-width: 340px; border-radius: 14px; box-shadow: 0 4px 32px rgba(255,179,71,0.13); padding: 36px 28px 28px 28px; position: relative; text-align: center; }
        .login-title { font-size: 1.3rem; font-weight: 700; color: #6a11cb; margin-bottom: 18px; letter-spacing: 1px; }
        .login-form input { width: 90%; padding: 10px; margin: 8px 0; border: 1px solid #6a11cb; border-radius: 8px; font-size: 1rem; background: #f7f9fc; transition: border-color 0.2s; }
        .login-form input:focus { border-color: #2575fc; outline: none; }
        .login-form button { width: 96%; margin-top: 10px; background: #6a11cb; color: #fff; border: none; padding: 10px; font-weight: 700; border-radius: 9px; cursor: pointer; font-size: 1rem; transition: background 0.2s; }
        .login-form button:hover { background: #2575fc; }
        .close-modal { position: absolute; top: 12px; right: 16px; font-size: 1.4rem; cursor: pointer; color: #6a11cb; font-weight: 700; background: none; border: none; }
        .login-tips { font-size: 0.98rem; color: #e74c3c; margin-top: 10px; min-height: 22px; transition: color 0.2s; }

        /* 页脚样式 */
        footer { background: #2d334a; color: white; padding: 50px 0 20px; }
        .footer-content { display: grid; grid-template-columns: repeat(4, 1fr); gap: 30px; }
        .footer-column h3 { font-size: 18px; margin-bottom: 20px; position: relative; padding-bottom: 10px; }
        .footer-column h3::after { content: ''; position: absolute; bottom: 0; left: 0; width: 30px; height: 2px; background: #ffd166; }
        .footer-column p, .footer-column a { color: #b8b8b8; margin-bottom: 10px; display: block; text-decoration: none; transition: color 0.3s; }
        .footer-column a:hover { color: #ffd166; }
        .social-links { display: flex; margin-top: 15px; margin-bottom: 20px; }
        .social-links a { width: 36px; height: 36px; border-radius: 50%; background: rgba(255,255,255,0.1); display: flex; justify-content: center; align-items: center; margin-right: 10px; transition: all 0.3s; }
        .social-links a:hover { background: #ffd166; color: #2d334a; }
        .copyright { text-align: center; padding-top: 30px; margin-top: 30px; border-top: 1px solid rgba(255,255,255,0.1); color: #888; font-size: 14px; }

        /* 响应式设计 */
        @media (max-width: 992px) {
            .recommendation-cards { grid-template-columns: repeat(2, 1fr); }
            .footer-content { grid-template-columns: repeat(2, 1fr); }
        }
        @media (max-width: 768px) {
            .navbar { flex-direction: column; align-items: flex-start; }
            .nav-links { margin-top: 15px; flex-wrap: wrap; }
            .nav-links li { margin: 0 15px 10px 0; }
            .search-box { margin-top: 15px; width: 100%; }
            .search-box input { width: 100%; }
            .ranking-item { flex-direction: column; align-items: flex-start; }
            .ranking-img { margin: 15px 0 0 0; width: 100%; height: 150px; }
        }
        @media (max-width: 576px) {
            .recommendation-cards { grid-template-columns: 1fr; }
            .footer-content { grid-template-columns: 1fr; }
        }

        /* 加载动画 */
        .loading { display: inline-block; width: 20px; height: 20px; border: 3px solid rgba(255,255,255,.3); border-radius: 50%; border-top-color: #fff; animation: spin 1s ease-in-out infinite; }
        @keyframes spin { to { transform: rotate(360deg); } }
        .loading-container { text-align: center; padding: 40px; color: #666; }
    </style>
</head>
<body>
    <!-- 导航栏 -->
    <header>
        <div class="container">
            <nav class="navbar">
                <div class="logo">
                    <i class="fas fa-mountain"></i>
                    <span>南京旅游小红书</span>
                </div>
                <ul class="nav-links">
                    <li><a href="/">首页</a></li>
                    <li><a href="/search">景点搜索</a></li>
                    <li><a href="#">旅游攻略</a></li>
                    <li><a href="#">美食探店</a></li>
                    <li><a href="#">关于我们</a></li>
                </ul>
                <div class="search-box">
                    <i class="fas fa-search"></i>
                    <input type="text" placeholder="搜索景点、攻略...">
                </div>
                <button class="login-btn" id="login-btn">登录</button>
                <div class="user-info" id="user-info" style="display:none;">
                    <span id="user-name"></span>
                    <button class="logout-btn" id="logout-btn">退出</button>
                </div>              
            </nav>
        </div>
    </header>
      <!-- 搜索结果  -->
    <section class="search-results-section" style="display: none;">
        <div class="container">
            <h2 class="section-title">搜索结果</h2>
            <p class="section-subtitle" id="search-subtitle">为您找到相关结果</p>
            <div class="recommendation-cards" id="search-results-container">
                <!-- 搜索结果将通过JS动态填充到这里 -->
            </div>
        </div>
    </section>

    <!-- 登录弹窗 -->
    <div class="login-modal" id="login-modal">
        <div class="login-box">
            <button class="close-modal" id="close-modal" title="关闭">×</button>
            <div class="login-title">登录</div>
            <form class="login-form" id="login-form" autocomplete="off">
                <input type="text" id="username" name="username" placeholder="用户名" maxlength="32" required>
                <input type="password" id="password" name="password" placeholder="密码" maxlength="32" required>
                <button type="submit">登录</button>
            </form>
            <div class="login-tips" id="login-tips"></div>
        </div>
    </div>

    <!-- 猜你喜欢区域 -->
    <section class="recommendation-section">
        <div class="container">
            <h2 class="section-title">猜你喜欢</h2>
            <p class="section-subtitle">根据您的浏览历史，我们为您推荐以下景点</p>
            <div class="homepage-search">
                <form action="/search" method="GET" style="display: flex; margin: 20px 0;">
                    <input type="text" name="q" placeholder="搜索景点..." 
                           style="flex: 1; padding: 10px; border: 2px solid #6a11cb; border-radius: 4px 0 0 4px;">
                    <button type="submit" 
                            style="padding: 10px 20px; background: #6a11cb; color: white; border: none; border-radius: 0 4px 4px 0;">
                        搜索
                    </button>
                </form>
            </div>  
            <div class="recommendation-cards" id="recommendation-cards">
                <div class="loading-container">
                    <div class="loading"></div>
                    <p>加载中...</p>
                </div>
            </div>
        </div>
    </section>

    <!-- 实时排名区域 -->
    <section class="ranking-section">
        <div class="container">
            <h2 class="section-title">小红书实时南京旅游景点排名
                <button class="refresh-btn" id="refresh-rank">刷新</button>
            </h2>
            <p class="section-subtitle">基于用户真实评价和互动数据生成的实时排名</p>
            <div class="ranking-list" id="ranking-list">
                <div class="loading-container">
                    <div class="loading"></div>
                    <p>加载中...</p>
                </div>
            </div>
        </div>
    </section>

    <!-- 页脚 -->
    <footer>
        <div class="container">
            <div class="footer-content">
                <div class="footer-column">
                    <h3>关于我们</h3>
                    <p>南京旅游小红书是专注于发现和分享南京旅游景点的平台，为用户提供最新、最真实的旅游资讯和推荐。</p>
                    <div class="social-links">
                        <a href="#"><i class="fab fa-weibo"></i></a>
                        <a href="#"><i class="fab fa-weixin"></i></a>
                        <a href="#"><i class="fab fa-qq"></i></a>
                        <a href="#"><i class="fab fa-instagram"></i></a>
                    </div>
                </div>
                <div class="footer-column">
                    <h3>热门景点</h3>
                    <a href="#">夫子庙</a>
                    <a href="#">中山陵</a>
                    <a href="#">玄武湖</a>
                    <a href="#">南京博物院</a>
                    <a href="#">总统府</a>
                </div>
                <div class="footer-column">
                    <h3>旅游攻略</h3>
                    <a href="#">一日游路线</a>
                    <a href="#">美食指南</a>
                    <a href="#">季节推荐</a>
                    <a href="#">交通指南</a>
                    <a href="#">住宿推荐</a>
                </div>
                <div class="footer-column">
                    <h3>联系我们</h3>
                    <p><i class="fas fa-map-marker-alt"></i> 南京市玄武区珠江路</p>
                    <p><i class="fas fa-phone"></i> 025-88888888</p>
                    <p><i class="fas fa-envelope"></i> info@nj-travel.com</p>
                </div>
            </div>
            <div class="copyright">
                <p>© 2025 南京旅游小红书 - 发现金陵之美。保留所有权利。</p>
            </div>
        </div>
    </footer>

    <script>
        // API配置
        const API_BASE = '';

        // 登录弹窗逻辑
        const loginBtn = document.getElementById('login-btn');
        const loginModal = document.getElementById('login-modal');
        const closeModalBtn = document.getElementById('close-modal');
        const loginForm = document.getElementById('login-form');
        const loginTips = document.getElementById('login-tips');
        const userInfo = document.getElementById('user-info');
        const userNameSpan = document.getElementById('user-name');
        const logoutBtn = document.getElementById('logout-btn');
        const refreshRankBtn = document.getElementById('refresh-rank');
        let user = null;
        let authToken = localStorage.getItem('authToken');

        // 初始化
        document.addEventListener('DOMContentLoaded', function() {
            // 检查是否有保存的token
            if (authToken) {
                verifyToken(authToken);
            } else {
                fetchRecommendations();
                fetchRankings();
            }

            // 绑定事件
            bindEvents();
        });

        function bindEvents() {
            loginBtn.onclick = function() {
                loginModal.classList.add('active');
                loginTips.textContent = '';
                loginForm.reset();
                document.getElementById('username').focus();
            };

            closeModalBtn.onclick = function() {
                loginModal.classList.remove('active');
            };

            document.addEventListener('keydown', function(e) {
                if(e.key === 'Escape') loginModal.classList.remove('active');
            });

            loginForm.onsubmit = function(e) {
                e.preventDefault();
                handleLogin();
            };

            logoutBtn.onclick = function() {
                handleLogout();
            };

            refreshRankBtn.onclick = function() {
                fetchRankings();
            };
        }

        function handleLogin() {
            loginTips.textContent = '';
            const username = loginForm.username.value.trim();
            const password = loginForm.password.value;

            if(!username || !password) {
                loginTips.textContent = "用户名和密码不能为空";
                return;
            }

            loginForm.querySelector('button[type="submit"]').disabled = true;
            loginTips.textContent = "正在登录...";

            fetch(API_BASE + '/api/login', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({username, password})
            })
            .then(res => res.json())
            .then(res => {
                loginForm.querySelector('button[type="submit"]').disabled = false;
                if(res && res.success) {
                    user = { name: res.name || username };
                    authToken = res.token;
                    localStorage.setItem('authToken', authToken);
                    loginModal.classList.remove('active');
                    showUser();
                    fetchRecommendations();
                } else {
                    loginTips.textContent = res.message || "登录失败，请检查用户名或密码";
                }
            })
            .catch((error)=>{
                loginForm.querySelector('button[type="submit"]').disabled = false;
                loginTips.textContent = "网络错误，请稍后重试";
                console.error('Login error:', error);
            });
        }

        function handleLogout() {
            user = null;
            authToken = null;
            localStorage.removeItem('authToken');
            showUser();
            fetchRecommendations();
        }

        function verifyToken(token) {
            fetch(API_BASE + '/api/verify', {
                method: 'GET',
                headers: {'Authorization': 'Bearer ' + token}
            })
            .then(res => res.json())
            .then(res => {
                if(res && res.success) {
                    user = { name: res.name };
                    showUser();
                    fetchRecommendations();
                } else {
                    localStorage.removeItem('authToken');
                    fetchRecommendations();
                    fetchRankings();
                }
            })
            .catch(() => {
                localStorage.removeItem('authToken');
                fetchRecommendations();
                fetchRankings();
            });
        }

        function showUser() {
            if(user && user.name) {
                loginBtn.style.display = 'none';
                userInfo.style.display = 'flex';
                userNameSpan.textContent = user.name;
            } else {
                loginBtn.style.display = 'inline-block';
                userInfo.style.display = 'none';
                userNameSpan.textContent = '';
            }
        }

        // 获取推荐景点
        function fetchRecommendations() {
            const el = document.getElementById('recommendation-cards');
            el.innerHTML = '<div class="loading-container"><div class="loading"></div><p>加载中...</p></div>';

            const headers = {};
            if (authToken) {
                headers['Authorization'] = 'Bearer ' + authToken;
            }

            fetch(API_BASE + '/api/recommend', {
                headers: headers
            })
            .then(res => res.json())
            .then(data => {
                if (data.success) {
                    renderRecommendations(data.data);
                } else {
                    el.innerHTML = '<div style="grid-column: span 4; color:#ff2e63; text-align:center;">' + data.message + '</div>';
                }
            })
            .catch((error)=>{
                console.error('Fetch recommendations error:', error);
                el.innerHTML = '<div style="grid-column: span 4; color:#ff2e63; text-align:center;">推荐景点加载失败，请稍后重试。</div>';
            });
        }

        function renderRecommendations(list) {
            const el = document.getElementById('recommendation-cards');
            el.innerHTML = '';

            if (list.length === 0) {
                el.innerHTML = '<div style="grid-column: span 4; text-align:center; color:#aaa;">暂无推荐景点</div>';
                return;
            }

            list.forEach(item => {
                const card = document.createElement('div');
                card.className = 'card';
                card.innerHTML = `
                    <div class="card-img">

                    </div>
                    <div class="card-content">
                        <h3 class="card-title">${item.name}</h3>
                        <p class="card-desc">${item.description || ''}</p>
                        <div class="card-stats">
                            <span><i class="fas fa-heart"></i> ${item.likes || 0}</span>
                            <span><i class="fas fa-comment"></i> ${item.comments || 0}</span>
                        </div>
                    </div>
                `;
                el.appendChild(card);
            });
        }

        // 获取景点排名
        function fetchRankings() {
            const el = document.getElementById('ranking-list');
            el.innerHTML = '<div class="loading-container"><div class="loading"></div><p>加载中...</p></div>';

            fetch(API_BASE + '/api/rank')
            .then(res => res.json())
            .then(data => {
                if (data.success) {
                    renderRankings(data.data);
                } else {
                    el.innerHTML = '<div style="color:#ff2e63;padding:20px;text-align:center;">' + data.message + '</div>';
                }
            })
            .catch((error)=>{
                console.error('Fetch rankings error:', error);
                el.innerHTML = '<div style="color:#ff2e63;padding:20px;text-align:center;">排名加载失败，请稍后重试。</div>';
            });
        }

        function renderRankings(list) {
            const el = document.getElementById('ranking-list');
            el.innerHTML = '';

            if (list.length === 0) {
                el.innerHTML = '<div style="padding:20px;text-align:center;color:#aaa;">暂无排名数据</div>';
                return;
            }

            list.forEach((item, idx) => {
                const rankingItem = document.createElement('div');
                rankingItem.className = 'ranking-item';
                rankingItem.innerHTML = `
                    <div class="ranking-number">${idx + 1}</div>
                    <div class="ranking-content">
                        <h3 class="ranking-title">${item.name}</h3>
                        <p class="ranking-desc">${item.description || ''}</p>
                        <div class="ranking-stats">
                            <span><i class="fas fa-heart"></i> ${item.likes || 0}</span>
                            <span><i class="fas fa-comment"></i> ${item.comments || 0}</span>
                            <span><i class="fas fa-bookmark"></i> ${item.bookmarks || 0}</span>
                        </div>
                    </div>
                    <div class="ranking-img">

                    </div>
                `;
                el.appendChild(rankingItem);
            });
        }
    </script>
</body>
</html>
"""

if __name__ == '__main__':
    init_database()
    app.run(debug=True, host='0.0.0.0', port=5000)